<?php

namespace App\Http\Controllers\TK_Api;

use App\Http\Requests\TK\GetOrderInfoRequest;
use App\Http\Requests\TK\OrderSubmitRequest;
use App\Models\Cdkey;
use App\Models\Course;
use App\Models\Order;
use App\Models\User;
use App\Service\TK\Course\CourseService;
use App\Service\Wechat\WechatPayService;
use Carbon\Carbon;
use DB;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Log;
use Symfony\Component\HttpFoundation\Response;

class OrderController extends ApiBaseController
{
    /**
     * 获取支付记录
     * @return JsonResponse|object
     */
    public function list() {
        $list = Order::where('tiku_order.userId', $this->user->id)
            ->leftJoin('tiku_cdkey', 'tiku_order.id', '=', 'tiku_cdkey.orderId')
            ->leftJoin('tiku_course', 'tiku_order.courseId', '=', 'tiku_course.id')
            ->select(['tiku_order.id as orderId', 'tiku_order.tradeNo', 'tiku_order.status as orderStatus', 'tiku_order.type', 'tiku_order.buyAt', 'tiku_order.payAt', 'tiku_cdkey.code as cdkey', 'tiku_cdkey.status as cdkeyStatus', 'tiku_course.id as courseId', 'tiku_course.fullName as courseName'])
            ->where('tiku_order.status', '<>', 5)
            ->orderByDesc('tiku_order.buyAt')
            ->get();

        return $this->restful($list);
    }

    /**
     * 获取订单支付信息
     * @param GetOrderInfoRequest $request
     * @param WechatPayService $payService
     * @return JsonResponse|object
     * @throws Exception
     */
    public function getOrderInfo(GetOrderInfoRequest $request, WechatPayService $payService) {
        $params = $request->validated();

        $order = Order::where('id', $params['orderId'])->orWhere('tradeNo', $params['orderId'])->first();
        if (!$order) throw new Exception('订单不存在', 404);

        $payInfo = $payService->sign($order->wxPrepayId);
        unset($payInfo['appId']);
        $payInfo['courseId'] = $order->courseId;
        $payInfo['orderId'] = $order->id;
        $payInfo['buyType'] = $order->type;
        $payInfo['tradeNo'] = $order->tradeNo;
        $payInfo['price'] = $order->price;

        return $this->restful($payInfo);
    }


    /**
     * 提交订单
     * @param OrderSubmitRequest $request
     * @param WechatPayService $payService
     * @return JsonResponse|object
     * @throws GuzzleException
     * @throws Exception
     */
    public function orderSubmit(OrderSubmitRequest $request, WechatPayService $payService) {
        $params = $request->validated();
        $course = Course::find($params['courseId']);
        if (!$course) return $this->restful(null, false, '学科不存在');
        $tradeNo = 'NO'.time().rand(1000, 9999);
        $price = $course->questionPrice;    // 价格

        // 微信下单
        $result = $payService->order([
            'body' => $params['type'] == 1 ? '购买学科' : '购买学科激活码',
            'tradeNo' => $tradeNo,
            'fee' => $price,
            'openid' => $this->user->wxOpenid
        ]);

        try {
            $order = new Order([
                'userId' => $this->user->id,
                'courseId' => $course->id,
                'tradeNo' => $tradeNo,
                'price' => $price,
                'type' => $params['type'],
                'buyAt' => Carbon::now(),
                'wxNonceStr' => $result['nonce_str'],
                'wxSign' => $result['sign'],
                'wxPrepayId' => $result['prepay_id']
            ]);
            DB::transaction(function () use ($course, $tradeNo, $params, $result, $price, $order) {
                $order->save();

                // 如果是激活码购买就创建激活码
                if ($params['type'] == 2) {
                    $cdkey = new Cdkey([
                        'userId' => $this->user->id,
                        'courseId' => $course->id,
                        'orderId' => $order->id,
                        'code' => 'K'.rand(1000000, 9999999),
                        'status' => 3,
                        'createdAt' => Carbon::now()
                    ]);
                    $cdkey->save();
                }
            });

            $payInfo = $payService->sign($result['prepay_id']);
            unset($payInfo['appId']);
            $payInfo['courseId'] = $course->id;
            $payInfo['orderId'] = $order->id;
            $payInfo['buyType'] = $order->type;
            $payInfo['tradeNo'] = $order->tradeNo;
            $payInfo['price'] = $order->price;

            return $this->restful($payInfo);
        }catch (Exception $e) {
            throw new Exception('下单失败', 200);
        }
    }

    /**
     * 微信支付结果通知
     * @param WechatPayService $payService
     * @return Response
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function wechatNotify(WechatPayService $payService) {
        Log::debug('[微信支付通知开始]'. Carbon::now()->format('Y-m-d H:i:s'));
        $response = $payService->app->handlePaidNotify(function ($message, $fail) {
            try {
                $order = Order::where('tradeNo', $message['out_trade_no'])->first();
                if ($order) {
                    if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                        // 用户是否支付成功
                        if (array_get($message, 'result_code') === 'SUCCESS') {
                            if ($order->status == 1) {
                                Db::transaction(function () use ($order, $message) {
                                    $order->status = 2;
                                    $order->wxTradeNo = $message['transaction_id']; // 微信订单号
                                    $order->payAt = Carbon::now();
                                    $order->save();

                                    if ($order->type == 2) {
                                        $cdkey = Cdkey::where('orderId', $order->id)->first();
                                        if ($cdkey && $cdkey->status !=1) {
                                            $cdkey->status = 1;
                                            $cdkey->save();
                                        }
                                    }
                                    if($order->type == 1) {
                                        $user = User::find($order->userId);
                                        $result = CourseService::buyCourse($user, 1, ['orderId' => $order->id]);
                                        if (!$result) throw new Exception();
                                    }
                                });
                            }
                        }
                    } else {
                        return $fail('通信失败，请稍后再通知我');
                    }
                }
                return true;
            }catch (\Exception $e) {
                Log::error('微信支付通知处理异常');
                Log::error(json_encode($e->getMessage()));
                Log::error(json_encode($e->getLine()));
                Log::error(json_encode($e->getFile()));
            }

            return $fail('通信失败，请稍后再通知我');
        });

        return $response->send();
    }
}
